using System;
using System.Collections.Generic;
using System.Threading;
using System.Text;

namespace WOWEquipOptimizer
{
    /// <summary>
    /// partial optimization, only non-locked slots are optimized
    /// </summary>
    public class OptimizePartial : Optimizer
    {
        public OptimizePartial()
        {           
        }
        public override void Optimize()
        {
            Monitor.Enter(m_Target);
            float maxfitness = m_MaxTV;
            int[] nonlockedslots = new int[Character.SlotCount - m_LockCount];
            int[] nlitemmult = new int[Character.SlotCount - m_LockCount];
            int counter = 0;
            for (int i = 0; i < m_Locks.Length; i++)
            {
                if (!m_Locks[i])
                {
                    nonlockedslots[counter++] = i;
                }
            }
            nlitemmult[0] = 1;
            for (int i = 1; i < nlitemmult.Length; i++)
            {
                int value = 1;
                for (int k = 1; k <=i; k++)
                {
                    value *= m_Items[nonlockedslots[k - 1]].Count;
                }
                nlitemmult[i] = value;
            }
            counter = 0;
            Item backup = Armor.None;
            int modvalue = (int)((m_ItemCount < 100) ? m_ItemCount : m_ItemCount / 100);
            while (counter < (int) m_ItemCount)
            {
                if (m_Abort) break;
                int slot = nonlockedslots[counter % nonlockedslots.Length];
                backup = (Item) m_Target.Slots[slot].Clone();
                m_Target.Slots[slot] = m_Items[slot][(counter / nlitemmult[counter % nonlockedslots.Length]) % m_Items[slot].Count];
                m_Target.Slots[slot].Enchant = backup.Enchant;
                bool valid = m_Target.evaluateEquip(m_Target.Slots);
                float fitness = -1;
                if (valid) fitness = m_Target.evaluateTF();
                if (fitness > maxfitness)
                {
                    maxfitness = fitness;
                }
                else
                {
                    m_Target.Slots[slot] = (Item)backup.Clone();
                }
                if (counter % modvalue == 0)
                {
                    if(UpdateGraphics != null) UpdateGraphics(fitness);
                }
                counter++;
                if (Optimizer.m_Abort) break;
            }
            Monitor.Exit(m_Target);
            base.Optimize();
            if (EnableNotification) Notify();
        }
    }
}
